import requests
import json
from typing import Dict, List
import os
from dotenv import load_dotenv
import hashlib
import random
import re

# 加载环境变量
load_dotenv()

def get_essay_from_api(title: str, progress_callback=None) -> Dict:
    """
    从DeepSeek API获取作文内容，支持流式传输和进度显示
    """
    api_key = load_api_key()
    if not api_key:
        if os.path.exists(".env"):
            load_dotenv()
            api_key = os.getenv("DEEPSEEK_API_KEY")
            if not api_key:
                raise ValueError("请在设置中配置DeepSeek API密钥")
        else:
            raise ValueError("请在设置中配置DeepSeek API密钥")
        
    url = "https://api.deepseek.com/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    prompt = f"""请根据以下题目生成一篇英语作文，并附上中文翻译。
题目：{title}

要求：
1. 生成一篇300词左右的英语作文，要求句式复杂，语言地道，内容丰富。真情实感。
2. 提供准确的中文翻译
3. 分析每个句子的主谓宾定状补成分，从句也要分析，使用以下英文符号标记：
   - 主语：&主语&
   - 谓语：*谓语*
   - 宾语：#宾语#
   - 定语：(定语)
   - 状语：[状语]
   - 补语：$补语$
4. 返回JSON格式，包含以下字段：
   - english: 英文原文（带标记）
   - chinese: 中文翻译（带标记）
   - analysis: 每个句子的成分分析
"""
    
    data = {
        "model": "deepseek-chat",
        "messages": [
            {"role": "system", "content": "你是一个专业的英语作文生成器，能够生成高质量的英语作文并提供准确的中文翻译。请严格按照要求的JSON格式返回内容。"},
            {"role": "user", "content": prompt}
        ],
        "temperature": 0.7,
        "max_tokens": 4000,
        "top_p": 0.95,
        "frequency_penalty": 0.0,
        "presence_penalty": 0.0,
        "stream": True
    }
    
    try:
        # 发送流式请求
        response = requests.post(url, headers=headers, json=data, stream=True)
        
        response.raise_for_status()
        
        # 用于存储完整的响应内容
        full_content = ""
        expected_sections = ["english", "chinese", "analysis"]
        completed_sections = set()
        
        # 处理流式响应
        for line in response.iter_lines():
            if line:
                line = line.decode('utf-8')
                if line.startswith('data: '):
                    try:
                        data = json.loads(line[6:])  # 去掉 'data: ' 前缀
                        if 'choices' in data and data['choices']:
                            delta = data['choices'][0].get('delta', {})
                            if 'content' in delta:
                                content = delta['content']
                                full_content += content
                                
                                
                                # 检查是否完成了各个部分
                                if '"english":' in full_content and "english" not in completed_sections:
                                    completed_sections.add("english")
                                    
                                if '"chinese":' in full_content and "chinese" not in completed_sections:
                                    completed_sections.add("chinese")
                                    
                                if '"analysis":' in full_content and "analysis" not in completed_sections:
                                    completed_sections.add("analysis")
                                    
                                
                                # 更新进度
                                if progress_callback:
                                    progress = len(completed_sections) / len(expected_sections)
                                    progress_callback(progress)
                    except json.JSONDecodeError as e:
                        
                        continue
        
        
        
        # 处理可能的 Markdown 格式
        if full_content.startswith("```json"):
            full_content = full_content[7:]  # 移除 ```json
        if full_content.endswith("```"):
            full_content = full_content[:-3]  # 移除结尾的 ```
        full_content = full_content.strip()  # 移除首尾空白
        
        try:
            # 尝试解析JSON响应
            result = json.loads(full_content)
            
            return result
        except json.JSONDecodeError as e:
            
            # 如果JSON解析失败，使用文本解析
            return parse_text_response(full_content)
            
    except requests.RequestException as e:
        
        raise ConnectionError(f"API请求失败：{str(e)}")
    except Exception as e:
        
        raise Exception(f"获取作文时发生错误：{str(e)}")

def parse_text_response(text: str) -> Dict:
    """
    解析API返回的文本响应
    """
    # 尝试提取英文和中文内容
    english_match = re.search(r'英文原文[：:]\s*(.*?)(?=中文翻译|$)', text, re.DOTALL)
    chinese_match = re.search(r'中文翻译[：:]\s*(.*?)(?=成分分析|$)', text, re.DOTALL)
    
    english = english_match.group(1).strip() if english_match else "&This& *is* (a sample) #essay#."
    chinese = chinese_match.group(1).strip() if chinese_match else "&这& *是* (一篇示例) #文章#。"
    
    # 尝试提取成分分析
    analysis_match = re.search(r'成分分析[：:]\s*(.*?)$', text, re.DOTALL)
    if analysis_match:
        analysis_text = analysis_match.group(1).strip()
        # 解析每个句子的成分
        sentences = re.split(r'[。.!?]', analysis_text)
        analysis = []
        for sentence in sentences:
            if not sentence.strip():
                continue
            # 尝试提取各个成分
            subject_match = re.search(r'主语[：:]\s*(\w+)', sentence)
            predicate_match = re.search(r'谓语[：:]\s*(\w+)', sentence)
            object_match = re.search(r'宾语[：:]\s*(\w+)', sentence)
            attribute_match = re.search(r'定语[：:]\s*([^,，]+)', sentence)
            adverbial_match = re.search(r'状语[：:]\s*([^,，]+)', sentence)
            complement_match = re.search(r'补语[：:]\s*([^,，]+)', sentence)
            
            analysis.append({
                "sentence": sentence.strip(),
                "subject": subject_match.group(1) if subject_match else None,
                "predicate": predicate_match.group(1) if predicate_match else None,
                "object": object_match.group(1) if object_match else None,
                "attribute": attribute_match.group(1) if attribute_match else None,
                "adverbial": adverbial_match.group(1) if adverbial_match else None,
                "complement": complement_match.group(1) if complement_match else None
            })
    else:
        # 默认分析
        analysis = [{
            "sentence": "This is a sample essay.",
            "subject": "This",
            "predicate": "is",
            "object": "essay",
            "attribute": "a sample",
            "adverbial": None,
            "complement": None
        }]
    
    return {
        "english": english,
        "chinese": chinese,
        "analysis": analysis
    }

def analyze_sentence(sentence: str) -> Dict:
    """
    分析句子的主谓宾定状补成分
    """
    # 使用正则表达式分析句子成分
    # 这是一个简化的实现，实际应用中可能需要更复杂的语法分析
    words = sentence.split()
    
    # 假设第一个词是主语
    subject = words[0] if words else None
    
    # 假设第二个词是谓语
    predicate = words[1] if len(words) > 1 else None
    
    # 假设最后一个词是宾语
    object_word = words[-1] if len(words) > 2 else None
    
    # 假设中间的词是定语
    attribute = " ".join(words[2:-1]) if len(words) > 3 else None
    
    return {
        "subject": subject,
        "predicate": predicate,
        "object": object_word,
        "attribute": attribute,
        "adverbial": None,
        "complement": None
    }

def parse_marked_text(text: str) -> List[Dict]:
    """
    解析带标记的文本，返回成分列表
    """
    components = []
    current_text = ""
    current_type = None
    
    # 使用正则表达式匹配标记
    pattern = r'[&*#()\[\]$]'
    matches = list(re.finditer(pattern, text))
    
    if not matches:
        # 如果没有标记，返回整个文本作为普通文本
        return [{"text": text, "type": "normal"}]
    
    # 处理第一个标记之前的内容
    if matches[0].start() > 0:
        components.append({"text": text[:matches[0].start()], "type": "normal"})
    
    # 处理标记之间的内容
    for i in range(len(matches)):
        start = matches[i].start()
        end = matches[i].end()
        char = text[start:end]
        
        if char == "&":
            if current_type is None:
                current_type = "subject"
            else:
                components.append({"text": current_text, "type": current_type})
                current_text = ""
                current_type = None
        elif char == "*":
            if current_type is None:
                current_type = "predicate"
            else:
                components.append({"text": current_text, "type": current_type})
                current_text = ""
                current_type = None
        elif char == "#":
            if current_type is None:
                current_type = "object"
            else:
                components.append({"text": current_text, "type": current_type})
                current_text = ""
                current_type = None
        elif char == "(":
            if current_type is None:
                current_type = "attribute"
        elif char == ")":
            if current_type == "attribute":
                components.append({"text": current_text, "type": current_type})
                current_text = ""
                current_type = None
        elif char == "[":
            if current_type is None:
                current_type = "adverbial"
        elif char == "]":
            if current_type == "adverbial":
                components.append({"text": current_text, "type": current_type})
                current_text = ""
                current_type = None
        elif char == "$":
            if current_type is None:
                current_type = "complement"
            else:
                components.append({"text": current_text, "type": current_type})
                current_text = ""
                current_type = None
        
        # 添加标记之间的文本
        if i < len(matches) - 1:
            next_start = matches[i+1].start()
            current_text += text[end:next_start]
        else:
            # 处理最后一个标记之后的内容
            current_text += text[end:]
    
    # 处理最后一个组件
    if current_text:
        components.append({"text": current_text, "type": current_type or "normal"})
    
    return components

def save_api_key(api_key: str):
    """
    保存DeepSeek API密钥到.env文件
    """
    with open(".env", "w", encoding="utf-8") as f:
        f.write(f"DEEPSEEK_API_KEY={api_key}")

def load_api_key() -> str:
    """
    从.env文件加载DeepSeek API密钥
    """
    return os.getenv("DEEPSEEK_API_KEY", "")